/*
 * Copyright (c) 2002-2003 by OpenSymphony
 * All rights reserved.
 */
package org.jackysoft.opensymphony.workflow.entity;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.jackysoft.util.ValidationUtils;
import org.jackysoft.util.XmlUtils;


/**
 * @author <a href="mailto:plightbo@hotmail.com">Pat Lightbody</a>
 */
public class ResultDescriptor extends AbstractDescriptor implements Validatable {
    //~ Instance fields ////////////////////////////////////////////////////////

    /**
	 * 
	 */
	private static final long serialVersionUID = 9189987133267776441L;
	protected List postFunctions = new ArrayList();
    protected List preFunctions = new ArrayList();
    protected List validators = new ArrayList();
    protected String displayName;
    protected String dueDate;
    protected String oldStatus;
    protected String owner=null;
    protected String status;
    protected boolean hasStep = false;
    protected int join;
    protected int split;
    protected int step = 0;

    //~ Constructors ///////////////////////////////////////////////////////////
  
    
    public  ResultDescriptor(org.dom4j.Element element) {
    	super(element);
    	this.init(element);
    }

    //~ Methods ////////////////////////////////////////////////////////////////

    public ResultDescriptor() {
		super();
		// TODO Auto-generated constructor stub
	}

	public void setDisplayName(String displayName) {
        if (getParent() instanceof ActionDescriptor) {
            if (((ActionDescriptor) getParent()).getName().equals(displayName)) {
                this.displayName = null; // if displayName==parentAction.displayName, reset displayName  

                return;
            }
        }

        this.displayName = displayName;
    }

   
    public String getDisplayName() {
        return displayName;
    }

    
    public String getDueDate() {
        return dueDate;
    }

    public void setJoin(int join) {
        this.join = join;
    }

    
    public int getJoin() {
        return join;
    }

    public void setOldStatus(String oldStatus) {
        this.oldStatus = oldStatus;
    }

    
    public String getOldStatus() {
        return oldStatus;
    }

    public void setOwner(String owner) {
    	this.owner = owner;
    }

    /**
     * @return
     * <dd>返回的即可能是用户id
     * <dd>也可能是${owner}这种形式的owner编号
     * <dd>所以规定,用户名不能是${owner}这种规则
     * 
     * */
    public String getOwner() {
        return owner;
    }

    
    public List getPostFunctions() {
        return postFunctions;
    }

   
    public List getPreFunctions() {
        return preFunctions;
    }

    public void setSplit(int split) {
        this.split = split;
    }

    public int getSplit() {
        return split;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public String getStatus() {
        return status;
    }

    public void setStep(int step) {
        this.step = step;
        hasStep = true;
    }

    public int getStep() {
        return step;
    }

  
   
    public List getValidators() {
        return validators;
    }

    public void validate() throws InvalidWorkflowDescriptorException {
        ValidationUtils.validate(preFunctions);
        ValidationUtils.validate(postFunctions);
        ValidationUtils.validate(validators);

        //if it's not a split or a join or a finish, then we require a next step
        if ((split == 0) && (join == 0) && !(getParent() instanceof ActionDescriptor && ((ActionDescriptor) getParent()).isFinish())) {
            StringBuffer error = new StringBuffer("Result ");

            if (getId() > 0) {
                error.append("#").append(getId());
            }

            error.append(" is not a split or join, and has no ");

            if (!hasStep) {
                throw new InvalidWorkflowDescriptorException(error.append("next step").toString());
            }

            if ((status == null) || (status.length() == 0)) {
                throw new InvalidWorkflowDescriptorException(error.append("status").toString());
            }
        }

        //taken out for now
        //if ((split != 0) && ((join != 0) || (oldStatus.length() > 0) || (step != 0) || (status.length() > 0) || (owner.length() != 0))) {
        //    throw new InvalidWorkflowDescriptorException("Result " + id + " has a split attribute, so should not any other attributes");
        //} else if ((join != 0) && ((split != 0) || (oldStatus.length() > 0) || (step != 0) || (status.length() > 0) || (owner.length() != 0))) {
        //    throw new InvalidWorkflowDescriptorException("Result has a join attribute, should thus not any other attributes");
        //} else if ((oldStatus.length() == 0) || (step == 0) || (status.length() == 0)) {
        //    throw new InvalidWorkflowDescriptorException("old-status, step, status and owner attributes are required if no split or join");
        //}
    }

    public void writeXML(PrintWriter out, int indent) {
        XmlUtils.printIndent(out, indent++);

        StringBuffer buf = new StringBuffer();
        buf.append("<unconditional-result");

        if (hasId()) {
            buf.append(" id=\"").append(getId()).append("\"");
        }

        if ((dueDate != null) && (dueDate.length() > 0)) {
            buf.append(" due-date=\"").append(getDueDate()).append("\"");
        }

        buf.append(" old-status=\"").append(oldStatus).append("\"");

        if (join != 0) {
            buf.append(" join=\"").append(join).append("\"");
        } else if (split != 0) {
            buf.append(" split=\"").append(split).append("\"");
        } else {
            buf.append(" status=\"").append(status).append("\"");
            buf.append(" step=\"").append(step).append("\"");

            if ((owner != null) && (owner.length() > 0)) {
                buf.append(" owner=\"").append(owner).append("\"");
            }

            if ((displayName != null) && (displayName.length() > 0)) {
                buf.append(" display-name=\"").append(displayName).append("\"");
            }
        }

        if ((preFunctions.size() == 0) && (postFunctions.size() == 0)) {
            buf.append("/>");
            out.println(buf.toString());
        } else {
            buf.append(">");
            out.println(buf.toString());
            printPreFunctions(out, indent);
            printPostFunctions(out, indent);
            XmlUtils.printIndent(out, --indent);
            out.println("</unconditional-result>");
        }
    }

      
    @Override
    protected void init(org.dom4j.Element result) {
    	oldStatus = result.attributeValue("old-status");
    	status = result.attributeValue("status");
    	
    	try {
    		setId(Integer.parseInt(result.attributeValue("id")));
    	} catch (NumberFormatException e) {
    	}
    	
    	dueDate = result.attributeValue("due-date");
    	
    	try {
    		split = Integer.parseInt(result.attributeValue("split"));
    	} catch (Exception ex) {
    	}
    	
    	try {
    		join = Integer.parseInt(result.attributeValue("join"));
    	} catch (Exception ex) {
    	}
    	
    	try {
    		step = Integer.parseInt(result.attributeValue("step"));
    		hasStep = true;
    	} catch (Exception ex) {
    	}
    	
    	owner = result.attributeValue("owner");
    	displayName = result.attributeValue("display-name");
    	buildElement(result, "validators", "validator", ValidatorDescriptor.class, this.validators, this);
    	buildElement(result, "pre-functions", "function", ValidatorDescriptor.class, this.preFunctions, this);
    	buildElement(result, "post-functions", "function", ValidatorDescriptor.class, this.postFunctions, this);   	   	
    
    }

    protected void printPostFunctions(PrintWriter out, int indent) {
        if (postFunctions.size() > 0) {
            XmlUtils.printIndent(out, indent++);
            out.println("<post-functions>");

            Iterator iter = postFunctions.iterator();

            while (iter.hasNext()) {
                FunctionDescriptor function = (FunctionDescriptor) iter.next();
                function.writeXML(out, indent);
            }

            XmlUtils.printIndent(out, --indent);
            out.println("</post-functions>");
        }
    }

    protected void printPreFunctions(PrintWriter out, int indent) {
        if (preFunctions.size() > 0) {
            XmlUtils.printIndent(out, indent++);
            out.println("<pre-functions>");

            Iterator iter = preFunctions.iterator();

            while (iter.hasNext()) {
                FunctionDescriptor function = (FunctionDescriptor) iter.next();
                function.writeXML(out, indent);
            }

            XmlUtils.printIndent(out, --indent);
            out.println("</pre-functions>");
        }
    }

	/**
	 * @param postFunctions the postFunctions to set
	 */
	public void setPostFunctions(List postFunctions) {
		this.postFunctions = postFunctions;
	}

	/**
	 * @param preFunctions the preFunctions to set
	 */
	public void setPreFunctions(List preFunctions) {
		this.preFunctions = preFunctions;
	}

	/**
	 * @param validators the validators to set
	 */
	public void setValidators(List validators) {
		this.validators = validators;
	}

	/**
	 * @param dueDate the dueDate to set
	 */
	public void setDueDate(String dueDate) {
		this.dueDate = dueDate;
	}
    
    
    
}
